home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
201-225
/
214
/
mandelvroom
/
src
/
orbitint.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
7KB
|
265 lines
/*
* MandelVroom 2.0
*
* (c) Copyright 1987,1989 Kevin L. Clague, San Jose, CA
*
* All rights reserved.
*
* Permission is hereby granted to distribute this program's source
* executable, and documentation for non-comercial purposes, so long as the
* copyright notices are not removed from the sources, executable or
* documentation. This program may not be distributed for a profit without
* the express written consent of the author Kevin L. Clague.
*
* This program is not in the public domain.
*
* Fred Fish is expressly granted permission to distribute this program's
* source and executable as part of the "Fred Fish freely redistributable
* Amiga software library."
*
* Permission is expressly granted for this program and it's source to be
* distributed as part of the Amicus Amiga software disks, and the
* First Amiga User Group's Hot Mix disks.
*
* contents: this file contains functions to calculate and draw orbits for
* fixed point (scaled int) math mode.
*/
#include "mandp.h"
#include "parms.h"
static double x_scale, y_scale;
static int x_center, y_center;
static int rightedge,botedge;
static struct RastPort *Rp;
extern SHORT MaxOrbit;
#define ORBSHIFT 27
#define ORBINT(f) ((int)((f)*(double)(1<<ORBSHIFT)))
InitIntOrbit()
{
register struct Window *Window;
register int width, height;
Window = OrbitWind;
Rp = Window->RPort;
width = (Window->Width-LEFTMARG-RIGHTMARG);
height = (Window->Height-TOPMARG-BOTMARG);
rightedge = width + LEFTMARG - 1;
botedge = height + TOPMARG - 1;
x_scale = y_scale = (float) height / (2.0 * (double)(1<<ORBSHIFT));
x_center = width/2 + LEFTMARG;
y_center = height/2 + TOPMARG;
}
static char first_flag;
DrawOrbitInt( Pict )
struct Picture *Pict;
{
struct IntPotParms Parms;
LONG creal, cimag;
LONG sreal, simag;
InitIntOrbit();
creal = ORBINT( Pict->RealLow + (MouseX-Pict->LeftMarg) * Pict->RealGap );
cimag = ORBINT( Pict->ImagLow + (MouseY-Pict->TopMarg) * Pict->ImagGap );
sreal = ORBINT( Pict->Real );
simag = ORBINT( Pict->Imag );
if ( Pict->pNode.ln_Type == MANDPICT ) {
Parms.C_Real = creal;
Parms.C_Imag = cimag;
Parms.ScreenReal = sreal;
Parms.ScreenImag = simag;
} else {
Parms.C_Real = sreal;
Parms.C_Imag = simag;
Parms.ScreenReal = creal;
Parms.ScreenImag = cimag;
}
Parms.MaxIteration = MaxOrbit;
/* Clear the window for next display plot */
SetAPen(Rp, 0);
RectFill(Rp, LEFTMARG,TOPMARG, rightedge, botedge);
SetAPen(Rp, HIGHLIGHTPEN);
first_flag = 0;
Orbit3216( &Parms );
}
PlotIntOrbit( zreal, zimag )
LONG zreal, zimag;
{
int x,y;
x = x_center + (int)((double) zreal * x_scale);
y = y_center + (int)((double) zimag * y_scale);
if (x >= LEFTMARG && x <= rightedge &&
y >= TOPMARG && y <= botedge &&
first_flag == 1 ) {
WritePixel( Rp, x, y );
}
first_flag = 1;
}
/*
* Orbit display for 32 bit math using 16 bit multiplies.
* It is written for the 68000 instruction set.
*/
Orbit3216( Parms )
struct IntPotParms *Parms;
{
LONG Height;
register struct IntPotParms *P = Parms;
register LONG cura, curb, cura2, curb2;
#asm
height equ -4
Bits2Shift equ 5
;
;
; d1 - BITS2SHIFT
; d2 - k
; d4 - a
; d5 - b
; d6 - a2
; d7 - b2
;
screenr equ 0
screeni equ 4
curx equ 8
cury equ 12
maxi equ 16
;
move.l #Bits2Shift,d1
move.l screenr(a2),d4
move.l screeni(a2),d5
move.w maxi(a2),d2
bra Fposa2
;
FKLoop
;
; cura = cura2 - curb2 + curx;
exg d6,d4 ; exchange cura and cura2
sub.l d7,d4 ; subtract curb
add.l curx(a2),d4 ; add curx
;
; curb = cura * curb >> 12;
move.l d6,d7 ; get copy of op1 sign bit
bpl Fpos1 ; get absolute value of op1
neg.l d6
Fpos1
eor.l d5,d7 ; calculate result sign
tst.l d5 ; get absolute value of op2
bpl Fpos2
neg.l d5
Fpos2
move.l d6,d0 ; get a copy of op1
swap d0 ; get high half of op1
move.w d0,d7 ; save a copy of high half
mulu d5,d0 ; multiply op2 low by op1 high
clr.w d0 ; clear least significant part
swap d0 ; put it in it's place
swap d5 ; get high half of op2
mulu d5,d6 ; multiply op2 high with op1 low
clr.w d6 ; clear least significant part
swap d6 ; put it in its place
mulu d7,d5 ; multiply op2 high by op1 high
add.l d0,d5 ; add partial results
add.l d6,d5 ; add partial results
tst.l d7 ; is the result negative?
bpl Fpos3
neg.l d5 ; yes, better negate it.
Fpos3
asl.l d1,d5 ; now, rescale it.
;
; curb += curb + cury;
add.l d5,d5 ; double it and add cury
add.l cury(a2),d5
Fposa2
;
; cura2 = cura * cura;
move.l d4,d0 ; get absolute value of a in d0
bpl Fposa
neg.l d0
Fposa
move.l d0,d6 ; copy absolute value into d6
swap d6 ; get high part in d6
mulu d6,d0 ; multiply high and low destroying low
clr.w d0 ; clear the least significant part
swap d0 ; put most sig. part in low half
mulu d6,d6 ; multiply high and high destroing high
add.l d0,d6 ; add in lower half twice
add.l d0,d6
asl.l d1,d6 ; get radix point back in correct place
bvs Fbailout
;
; curb2 = curb * curb;
move.l d5,d0 ; get absolute value of a in d0
bpl Fposb
neg.l d0
Fposb
move.l d0,d7 ; copy absolute value into d7
swap d7 ; get high part in d7
mulu d7,d0 ; multiply high and low destroying low
clr.w d0 ; clear the least significant part
swap d0 ; put most sig. part in low half
mulu d7,d7 ; multiply high and high destroing high
add.l d0,d7 ; add in lower half twice
add.l d0,d7
asl.l d1,d7 ; get radix point back in correct place
bvs Fbailout
;
movem.l .saveregs,-(sp)
;
#endasm
PlotIntOrbit(cura,curb);
#asm
;
movem.l (sp)+,.saveregs
;
move.l d6,d0 ; if (cura2 + curb2 >= 4) goto bailout;
add.l d7,d0
bvs Fbailout
;
dbra d2,FKLoop
; addq #1,d2
Fbailout
move.w maxi(a2),d0
sub.w d2,d0
sub.w #1,d0
ext.l d0
#endasm
;;
}
#asm
.saveregs reg d0-d3/a2
#endasm